#ifndef VERTEX_H_
#define VERTEX_H_

#include <string>
#include "util/LinkedList.h"
#include "core/exceptions/DuplicateElementException.h"

/*
 * Clase que representa un vertice del grafo. Tiene un identificador
 * unico y dos coordenadas que lo posicionan (X e Y). Ademas tiene
 * un conjunto de aristas salientes.
 */
class Vertex {
public:

	/*
	 * Constructor. Recibe el id, y las coordenadas de la posicion.
	 * Valores por defecto para las coordenadas son 0.0.
	 */
	Vertex(std::string id, double x = 0.0, double y = 0.0);

	/*
	 * Destructor.
	 */
	virtual ~Vertex();

	/*
	 * Compara al vertice con otro. Se iguala por id.
	 */
	virtual bool equals(Vertex* other);

	/*
	 * Getter del id.
	 */
	virtual std::string getId();

	/*
	 * Getter de la coordenada X de la posicion.
	 */
	virtual double getPositionX();

	/*
	 * Getter de la coordenada Y de la posicion.
	 */
	virtual double getPositionY();

	/*
	 * Inner class que representa la arista. Consta de un id, dos
	 * vertices de los extremos, una distancia en metros y una velocidad
	 * maxima en Km/h para transitar por el vertice.
	 */
	class Edge {
	public:

		/*
		 * Constructor. Recibe un id, los vertices de los extremos, la
		 * distancia y la velocidad maxima.
		 */
		Edge(std::string id, Vertex* origin, Vertex* destination,
				double distanceInMeters = 0.0, double speedInKMH = 0.0);

		/*
		 * Destructor.
		 */
		virtual ~Edge();

		/*
		 * Compara a la arista con otra.
		 */
		virtual bool equals(Vertex::Edge* other);

		/*
		 * Getter del id.
		 */
		virtual std::string getId();

		/*
		 * Getter del vertice de origen.
		 */
		virtual Vertex* getOrigin();

		/*
		 * Getter del vertice destino.
		 */
		virtual Vertex* getDestination();

		/*
		 * Getter de la distancia en metros.
		 */
		virtual double getDistanceInMeters();

		/*
		 * Getter de la velocidad en Km/h.
		 */
		virtual double getSpeedInKMH();

	private:
		void setId(std::string id);
		void setOrigin(Vertex* origin);
		void setDestination(Vertex* destination);
		void setDistanceInMeters(double distance);
		void setSpeedInKMH(double speed);
		std::string id;
		Vertex* origin;
		Vertex* destination;
		double distanceInMeters;
		double speedInKMH;
	};

	/*
	 * Agrega una arista al conjunto de aristas salientes. Devuleve
	 * al vertice.
	 * Devuelve DuplicateElementException en caso de ya tener la arista.
	 */
	virtual Vertex* addOutgoingEdge(Vertex::Edge* edge)
			throw (DuplicateElementException);

	/*
	 * Getter del conjunto de aristas salientes (LinkedList).
	 */
	virtual util::LinkedList<Vertex::Edge*>* getOutgoingEdges();

private:
	void setId(std::string id);
	void setPositionX(double x);
	void setPositionY(double y);
	std::string id;
	double position_x;
	double position_y;
	util::LinkedList<Vertex::Edge*> outgoingEdges;
};

#endif /* VERTEX_H_ */
